﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Snowdreamist.ComponentModel.Plugin;
using Snowdreamist.Threading;
using Snowdreamist.Windows.Notification;

namespace Snowdreamist.ComponentModel.MEF.Notification
{
    public class MEFNotificationService : NotificationService
    {
        private static readonly ImportedPluginProperty<INotificationConsumer, INotificationConsumerMetadata> NotificationConsumerPluginProperty
            = ImportedPluginProperty.Create<INotificationConsumer, INotificationConsumerMetadata>(new Guid(), typeof(MEFNotificationService));

        private IEnumerable<ImportedPlugin<INotificationConsumer, INotificationConsumerMetadata>> ConsumerPlugins
        {
            get
            {
                return NotificationConsumerPluginProperty.GetValuesWithMetadata(this);
            }
        }

        public MEFNotificationService()
        {
            var plugins = this.ConsumerPlugins.ToArray();

            // Do not support multi-consumer for one scope at present
            if (plugins.Length > 3)
                throw new InvalidOperationException("Too many notification consumers");

            ImportedPlugin<INotificationConsumer, INotificationConsumerMetadata>[] consumers =
                new ImportedPlugin<INotificationConsumer, INotificationConsumerMetadata>[3];

            foreach (var plg in plugins)
            {
                if (consumers[(int)plg.Metadata.Scope] == null)
                {
                    consumers[(int)plg.Metadata.Scope] = plg;
                }
                else
                {
                    throw new InvalidOperationException("Too many notification consumers for scope: " + plg.Metadata.Scope.ToString());
                }
            }

            // run consumers
            foreach (var con in consumers)
                if (con != null)
                    BackgroundJob.Run(new Action<ImportedPlugin<INotificationConsumer, INotificationConsumerMetadata>>(plg =>
                        {
                            plg.Plugin.HandleNotification(this.WaitNotifications(plg.Metadata.Scope));
                        }), "Notification Consumer Waiting Job for Scope: " + con.Metadata.Scope.ToString(), con);
        }
    }
}